#pragma once

#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <vector>
#include <stdint.h>
#include <ctime>

#define NUM 16
template <class T>
class RingQueue
{
private:
    std::vector<T> q;
    int _cap;
    // 描述空间的信号量
    sem_t balk_sem;
    // 描述数据的信号量
    sem_t data_sem;
    // 消费者要消费的数据的下标
    int c_pos;
    // 生产者要生产的数据的下标
    int p_pos;

private:
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }

public:
    RingQueue(int cap = NUM) : _cap(cap), c_pos(0), p_pos(0)
    {
        q.resize(cap);
        // 初始化信号量，其中描述空间的信号量的大小设置为cap
        // 描述数据的信号量的大小设置为0
        sem_init(&balk_sem, 0, cap);
        sem_init(&data_sem, 0, 0);
    }
    void Push(const T &in)
    {
        // 当生产了一个数据，要对balk_sem进行P操作，对data_sem进行V操作
        P(balk_sem);
        q[p_pos] = in;
        p_pos++;
        // 取模，保证这个队列是循环队列
        p_pos %= _cap;
        V(data_sem);
    }

    void Pop(T &out)
    {
        P(data_sem);
        out = q[c_pos];
        c_pos++;
        c_pos %= _cap;
        V(balk_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&balk_sem);
        sem_destroy(&data_sem);
    }
};